package ar.uba.is2.ec.matem.exec.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import ar.uba.is2.common.threads.ThreadManager;
import ar.uba.is2.ec.matem.exec.Despachador;
import ar.uba.is2.ec.matem.exec.Ejecutor;
import ar.uba.is2.ec.matem.modelo.ModeloEjecutable;

public class DespachadorSimple implements Despachador {

	private static final DespachadorSimple instance = new DespachadorSimple();

	public static final DespachadorSimple getInstance() {
		return instance;
	}
	
	private Collection<Ejecutor> ejecutores = new ArrayList<Ejecutor>();
	
	private BlockingQueue<ModeloEjecutable> modelosADespachar = new LinkedBlockingQueue<ModeloEjecutable>();
	
	public DespachadorSimple() {
		
		DespachadorDaemon despachadorDaemon = new DespachadorDaemon();
		ThreadManager.instance.crearYCorrerThread(despachadorDaemon);
	}

	public void registrarEjecutor(Ejecutor ejecutor) {
		this.ejecutores.add(ejecutor);
	}
	
	@Override
	public void despachar(ModeloEjecutable modeloEjecutable) {
		try {
			this.modelosADespachar.put(modeloEjecutable);
		} catch (InterruptedException e) {
		}
	}
	
	private class DespachadorDaemon implements Runnable {

		@Override
		public void run() {
			try {
				while (true) {
					
					ModeloEjecutable modeloEjecutable = DespachadorSimple.this.modelosADespachar.take();
					
					Ejecutor ejecutor = elegirEjecutor();

					if (ejecutor != null) {
						ejecutor.asignarModelo(modeloEjecutable);
					}
				}
			} catch (InterruptedException e) {
			}
		}

		protected Ejecutor elegirEjecutor() {

			for (Ejecutor ejecutor : DespachadorSimple.this.ejecutores) {
				if (!ejecutor.isOcupado()) {
					return ejecutor;
				}
			}
			return null;
		}
	}

}
